<?php


namespace app\common\cachemodel;


use app\common\cachemodel\AstroChange as AstroChangeModel;
use app\common\lib\astrolog\Astrolog;
use app\common\lib\Util;
use app\common\model\BaseCache;
use think\Env;
use XznsTools\cache\CacheManage;

class AstroChange extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.app_astro_change';
    protected $cacheModel = 'astro.change_day_timezone';

    /**
     * 获取 某天 天象变动数据
     * @param string $date 20200608
     * @param $timezone
     * @return array
     * @throws \Exception
     */
    public function getChangeDayList(string $date, $timezone): array
    {
        $astroChangeData = CacheManage::getInstance()->setCacheConfig($this->cacheModel, date('Ymd', strtotime($date)) . ':' . $timezone)
            ->getDataAndSet(function () use ($date, $timezone)
            {
                $startTime = strtotime(date('Y-m-d 00:00:00', strtotime($date)));
                $endTime = strtotime(date('Y-m-d 23:59:59', strtotime($date)));
                $startDate = gmdateModify('Y-m-d H:i:s', $startTime, $timezone, 0);
                $endDate = gmdateModify('Y-m-d H:i:s', $endTime, $timezone, 0);

                try
                {
                    $astroChangeData = $this->where('time', 'between', [$startDate, $endDate])->select();
                    if ($astroChangeData)
                    {
                        $astroChangeData = collection($astroChangeData)->toArray();
                    }
                }
                catch (\Exception $e)
                {
                    $astroChangeData = [];
                }

                return json_encode($astroChangeData);
            });

        if (is_string($astroChangeData))
        {
            $astroChangeData = json_decode($astroChangeData, true);
        }

        $data = [];
        $listData = [];
        if ($astroChangeData)
        {
            $planetsData = config('astrolog.planets_name');
            $signsData = config('astrolog.sign_name');
            foreach ($astroChangeData as $item)
            {
                switch ($item['type'])
                {
                    case 1:
                        $text = explode('|', $planetsData[$item['pid']])[3] . '进入' . explode('|', $signsData[$item['in_sign_id']])[3];
                        break;
                    case 2:
                        $text = explode('|', $planetsData[$item['pid']])[3] . '在' . explode('|', $signsData[$item['in_sign_id']])[3] . ((int)$item['speed'] === 1 ? '顺行' : '逆行');
                        break;
                    case 3:
                        $text = explode('|', $signsData[$item['in_sign_id']])[3] . '日食';
                        break;
                    case 4:
                        $text = explode('|', $signsData[$item['in_sign_id']])[3] . '月食';
                        break;
                    case 5:
                        $text = explode('|', $signsData[$item['in_sign_id']])[3] . '新月';
                        break;
                    case 6:
                        $text = explode('|', $signsData[$item['in_sign_id']])[3] . '满月';
                        break;
                    default:
                        $text = '';
                        break;
                }

                if ($text)
                {
                    $itemTime = gmdateModify('Y-m-d H:i:s', strtotime($item['time']), 0, $timezone, false);
                    $ch = date('H', $itemTime);
                    $ci = date('i', $itemTime);
                    $ci = date('s', $itemTime) > 0 ? $ci + 1 : $ci;
                    // 处理分钟数变成60的问题
                    if ($ci >= 60)
                    {
                        $ci = 59;
                    }
                    $timestamp = strtotime("{$item['time']} +8 hours");// 转换成东8区时间搓

                    $min = date('i', $timestamp);
                    $min = date('s', $timestamp) > 0 ? $min + 1 : $min;
                    // 处理分钟数变成60的问题
                    if ($min >= 60)
                    {
                        $min = 59;
                    }

                    $data[$timestamp] = [
                        'time' => $ch . ":" . sprintf("%02d", $ci),
                        'astro_text' => $text,
                        'target' => 'local',
                        'link' => 'astrolable?chart=now&date=' . date('Y-m-d', $timestamp) . '&hour=' . date('H', $timestamp) . '&min=' . sprintf("%02d", $min) . '&need_auth=1'
                    ];
                    $listData[] = [
                        'type' => $item['type'],
                        'pid' => $item['pid'],
                        'in_sign_id' => $item['in_sign_id'],
                        'speed' => $item['speed'],
                        'text' => $text,
                        'time' => $item['time'] // 0时区时间
                    ];
                }
            }
            asort($data);
            $data = array_values($data);
        }

        return [
            'listData' => $listData,
            'resData' => $data
        ];
    }

    /**
     * 获取 某月 天象变动数据
     * @param string $date 年月 2020-06
     * @param int|float $timezone 时区
     * @return array
     * @throws \Exception
     */
    public function getChangeMonthList(string $date, $timezone): array
    {
        $astroChangeData = CacheManage::getInstance()->setCacheConfig('astro.change_month_timezone', date('Ym', strtotime($date)) . ':' . $timezone)
            ->getDataAndSet(function () use ($date, $timezone)
            {
                $startTime = date('Y-m-01 00:00:00', strtotime($date));
                $endTime = strtotime(date('Y-m-d 23:59:59', strtotime("$startTime +1 month -1 day")));
                $startDate = gmdateModify('Y-m-d H:i:s', strtotime($startTime), $timezone, 0);
                $endDate = gmdateModify('Y-m-d H:i:s', $endTime, $timezone, 0);

                try
                {
                    $astroChangeData = (new AstroChangeModel())->where('time', 'between', [$startDate, $endDate])->select();
                    if ($astroChangeData)
                    {
                        $astroChangeData = collection($astroChangeData)->toArray();
                    }
                }
                catch (\Exception $e)
                {
                    $astroChangeData = [];
                }

                return json_encode($astroChangeData);
            });

        if (is_string($astroChangeData))
        {
            $astroChangeData = json_decode($astroChangeData, true);
        }

        return $astroChangeData;
    }


    /**
     * 获取星象变动词条
     * @param string $date 星象变动的日期
     * @param int $timezone 时区
     * @param array $changeData 星象变动数据
     * @param array $recodeInfo 档案信息
     * @param bool $isSendDingDing 当词条缺失的时候是否发送钉钉消息提醒
     * @return array
     * @throws \Exception
     */
    public function getChangeText(string $date, $timezone, array $changeData, array $recodeInfo, bool $isSendDingDing): array
    {
        $astroObj = Astrolog::getInstance()
            ->setRecode1($recodeInfo)
            ->setExecPrefix(config('astrolog.prefix'))
            ->setIsAstrolabe(false)
            ->setUserSetting(config('astroset.setting1'))
            ->setGetDatas(['transits']);
        $recodeData = $astroObj->getRecode1();

        $resData = [];
        $astroChangeTextModel = new AstroChangeText();
        foreach ($changeData as $value)
        {
            $dailyTime = strtotime($value['time']);
            $timeinfo = ['year' => date('Y', $dailyTime), 'month' => date('m', $dailyTime), 'day' => date('d', $dailyTime), 'hour' => date('H', $dailyTime), 'minute' => date('i', $dailyTime), 'second' => date('s', $dailyTime)];
            $timeinfo['timezone'] = 0;// 天象变动时间均为0时区时间
            $timeinfo['is_summer'] = isSummerTime($timeinfo['hour'], $timeinfo['minute'], $timeinfo['second'], $timeinfo['month'], $timeinfo['day'], $timeinfo['year']) ? 1 : 0;
            // 档案出生地经纬度
            $timeinfo['longitude'] = $recodeData['birth_lng'];
            $timeinfo['latitude'] = $recodeData['birth_lat'];
            // 获取行运星落本命宫位   例如：水星落本命宫位  $transitsData[1]['planets'][2]['in_house_id']
            $transitsData = $astroObj->setAdvance($timeinfo)
                ->getAstroDatas()
                ->getDatas('transits');

            $where = [
                'type' => $value['type'],
                'pid' => $value['pid'],
                'sid' => $value['in_sign_id'],
                'hid' => $transitsData[1]['planets'][$value['pid']]['in_house_id'],
                'speed' => $value['speed'],
            ];

            $changeText = $astroChangeTextModel->getChangeText($where);

            if ($changeText)
            {
                $resData[] = [
                    'title' => $value['text'],
                    'content' => $changeText
                ];
            } else
            {
                // 词条缺失 判断是否发送钉钉消息
                $nowDatetime = strtotime(date('Y-m-d'));
                $requestDatetime = strtotime($date);
                $datetimeDiff = $requestDatetime - $nowDatetime;
                if ($isSendDingDing || ($datetimeDiff > 0 && $datetimeDiff <= 86400 * 2))
                { // 需要发送钉钉消息时则发送钉钉消息
                    $env = Env::get('host.name', 'local');
                    $this->sendMsg('[' . $env . ']天象词条缺失',
                        "# 天象词条缺失 \r\n\r\n " .
                        "环境：{$env} \r\n\r\n " .
                        "日期：{$date} \r\n\r\n " .
                        "天象：{$value['text']} \r\n\r\n " .
                        "宫位：第{$where['hid']}宫",
                        Env::get('host.admin_domain') . '/admin/app_astro_change_text/index.html?' . http_build_query($where));
                }
            }
        }
        return $resData;
    }

    private function sendMsg($title, $contentMsg, $herfUrl)
    {
        $time = time() * 1000;
        if (Env::get('host.name', 'local') !== 'online')
        {
            // PHP钉钉群
            $sec = 'SECcd9cc7f9e863073d9ebd0a2d0c9ed2f38d38ffcd67b700866d97ab3f919eb419';
            $sign = urldecode(base64_encode(hash_hmac('sha256', $time . "\n" . $sec, $sec, true)));
            $url = 'https://oapi.dingtalk.com/robot/send?access_token=b93977081e77642ab22db0e369abc12e08389a99441b3cc2ed6b3f675d8e9d7e';// 钉钉推送地址

        } else
        {
            // 内容异常通知群
            $sec = 'SEC72aa02d0d694a73cc28541cbf710a863f8e0b99f867b2d5a170873548eda9af0';
            $sign = urldecode(base64_encode(hash_hmac('sha256', $time . "\n" . $sec, $sec, true)));
            $url = 'https://oapi.dingtalk.com/robot/send?access_token=987360b12e1f567e2ecb9f500bfe6ae42480d66b937fd19fc69cb904238d045a';// 钉钉推送地址
        }

        $url .= "&timestamp={$time}&sign={$sign}";

        Util::sendDingMsg($url, $title, $contentMsg, 3, $herfUrl);
    }
}
